/**************************************************************************//**
 * @item     CosyOS-III Kernel
 * @file     os_handler.c
 * @brief    OS_SysTick_Handler and sPendSV_Handler
 * @author   迟凯峰
 * @version  V1.0.0
 * @date     2025.02.08
 ******************************************************************************/

#include "os_var.h"
#include "os_api.h"
#include "sv_com.h"
#include "sv_create.h"
#include "sv_tick.h"
#include "ur_api.h"
#include "ur_eapi.h"

#if SYSCFG_DEBUGGING == __ENABLED__
static s_u32_t usedtime[2] = {0};
#endif

void OS_SysTick_Handler(void) MCUCFG_SYSTICK_ATTRIBUTE
{
	void tick_hook(void);
	#if OS_TIMINTTOTAL || OS_TIMQRYTOTAL
	s_u8_t _SYS_REG_ i;
	#endif
	#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__
	static m_tick_t tick_temp;
	#endif
	s_tasknode_tsp _SYS_REG_ htask;
	
	/* 清除中断标志位 */
	mSysTick_Clear;
	
	/* 系统滴答时间统计开始 */
	#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__
	if(s_sign_taskmgr){
		tick_temp = mSysTick_Counter;
	}
	#endif
	
	/* 软件RTC */
	#if SYSCFG_SOFTRTC == __ENABLED__
	if(true){
		static
		#if SYSCFG_SYSTICKCYCLE > 1000000UL / 65536
		s_u16_t
		#else
		s_u32_t
		#endif
		_SYS_MEM_ counter = 0;
		if(s_sign_every.set){
			s_sign_every.set = false;
			counter = 1000000UL / SYSCFG_SYSTICKCYCLE / 2;
		}
		else{
			if(counter < 1000000UL / SYSCFG_SYSTICKCYCLE - 1){
				counter++;
				if(counter == 1000000UL / SYSCFG_SYSTICKCYCLE / 2){
					s_sign_every.halfsec = true;
				}
			}
			else{
				counter = 0;
				s_sign_every.halfsec = true;
				s_sign_every.second = true;
				if(s_rtc.second < 59) s_rtc.second++;
				else{
					s_rtc.second = 0;
					s_sign_every.minute = true;
					if(s_rtc.minute < 59) s_rtc.minute++;
					else{
						s_rtc.minute = 0;
						s_sign_every.hour = true;
						if(s_rtc.hour < 23) s_rtc.hour++;
						else{
							s_rtc.hour = 0;
							s_sign_every.day = true;
							if(s_rtc.day < 7) s_rtc.day++;
							else s_rtc.day = 1;
							if(s_rtc.date < (s_rtc.month == 2 ? s_month2day : s_month0day[s_rtc.month])) s_rtc.date++;
							else{
								s_rtc.date = 1;
								s_sign_every.month = true;
								if(s_rtc.month < 12) s_rtc.month++;
								else{
									s_rtc.month = 1;
									s_sign_every.year = true;
									if(s_rtc.year < 99) s_rtc.year++;
									else{
										s_rtc.year = 0;
										s_rtc.yeah++;
									}
								}
							}
						}
					}
				}
				#if SYSCFG_GETRTC_INT == __ENABLED__
				sv_update_rtccopy();
				#endif
			}
		}
	}
	#endif
	
	/* 运行时间统计 */
	#if SYSCFG_RUNTIME_COUNT == __ENABLED__
	if(true){
		static
		#if SYSCFG_SYSTICKCYCLE > 1000000UL / 65536
		s_u16_t
		#else
		s_u32_t
		#endif
		_SYS_MEM_ counter = 0;
		if(counter < 1000000UL / SYSCFG_SYSTICKCYCLE - 1){
			counter++;
		}
		else{
			counter = 0;
			if(s_runtime.second < 59) s_runtime.second++;
			else{
				s_runtime.second = 0;
				if(s_runtime.minute < 59) s_runtime.minute++;
				else{
					s_runtime.minute = 0;
					if(s_runtime.hour < 23) s_runtime.hour++;
					else{
						s_runtime.hour = 0;
						s_runtime.day++;
					}
				}
			}
		}
	}
	#endif
	
	/* 滴答钩子 */
	#if SYSCFG_TICKHOOK == __ENABLED__
	tick_hook();
	#endif
	
	/* 任务管理器 */
	#if SYSCFG_DEBUGGING == __ENABLED__
	if(s_sign_debug_send){
		s_sign_debug_send = false;
		tTimQry_ms(OS_TMID_DEBUGHOOK, 30);
	}
	if(s_sign_debug_recv){
		s_sign_debug_recv = false;
		tTimInt_ms(OS_TMID_DEBUGGER, 15);
	}
	#endif
	
	/* 定时中断 */
	#if OS_TIMINTTOTAL
	i = OS_TIMINTTOTAL;
	while(i--){
		if(s_timint_handle[i]->timer){
			s_timint_handle[i]->timer--;
			if(!s_timint_handle[i]->timer){
				if(s_timint_handle[i]->autoreload){
					s_timint_handle[i]->timer = s_timint_handle[i]->reload;
				}
				if(s_timint_handle[i]->hookortask){
					sResumeTask_TimInt(i);
				}
				else{
					sCallHook_TimInt(i);
				}
			}
		}
	}
	#endif
	
	/* 定时查询 */
	#if OS_TIMQRYTOTAL
	i = OS_TIMQRYTOTAL;
	while(i--){
		if(s_timqry_handle[i]->timer && s_timqry_handle[i]->timer < (s_timqry_t)~0){
			s_timqry_handle[i]->timer--;
		}
		if(!s_timqry_handle[i]->timer){
			if((*s_timqry_handle[i]->event)()){
				if(s_timqry_handle[i]->autoreload){
					s_timqry_handle[i]->timer = s_timqry_handle[i]->reload;
				}
				else{
					s_timqry_handle[i]->timer = ~0;
				}
				if(s_timqry_handle[i]->hookortask){
					sResumeTask_TimQry(i);
				}
				else{
					sCallHook_TimQry(i);
				}
			}
		}
	}
	#endif
	
	/* 阻塞延时 */
	/* 定时器链表中的任务状态：就绪、阻塞、挂起、停止、删除。*/
	if(true){
		#define hcurr htask
		s_tasknode_tsp _SYS_REG_ hlast;
		hcurr = s_list_timer;
		while(hcurr != OS_VOID){
			if(hcurr->status == OS_STATUS_BLOCKED){
				if(hcurr->timer && hcurr->timer < (s_delay_t)~0){
					hcurr->timer--;
					if(!hcurr->timer){
						hcurr->status = OS_STATUS_READY;
						sv_task_add_ready(hcurr);
						goto __NODE_REMOVE;
					}
				}
			}
			else if(hcurr->status & OS_STATUS_SUSPENDED){
				if((hcurr->status & (~OS_STATUS_SUSPENDED & 0xFF)) == OS_STATUS_READY){
					goto __NODE_REMOVE;
				}
			}
			else if(hcurr->status == OS_STATUS_DELETED){
				if(hcurr->create && hcurr->next_b == OS_NULL){
					sv_free_task(hcurr);
				}
				goto __NODE_REMOVE;
			}
			else{
				goto __NODE_REMOVE;
			}
			hlast = hcurr;
			hcurr = hcurr->next_t;
			continue;
			__NODE_REMOVE:
			if(hcurr == s_list_timer){
				s_list_timer = hcurr->next_t;
				hcurr->next_t = OS_NULL;
				hcurr = s_list_timer;
			}
			else{
				hlast->next_t = hcurr->next_t;
				hcurr->next_t = OS_NULL;
				hcurr = hlast->next_t;
			}
		}
		#undef hcurr
	}
	
	/* 就绪延时 */
	if(s_sign_ready_delay){
		if(s_task_current->timer && s_task_current->timer < (s_delay_t)~0){
			s_task_current->timer--;
			if(!s_task_current->timer){
				s_sign_ready_delay = false;
			}
		}
	}
	
	/* 时间片 */
	#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
	if(s_task_current->tc_counter < OS_TIMESHARING(s_task_current)){
		s_task_current->tc_counter++;
	}
	else{
		s_sign_schedule = true;
	}
	#endif
	
	/* 安全运行时 */
	/* 超时链表中的任务状态：超时、挂起、停止、删除。*/
	#if SYSCFG_SAFERUNTIME == __ENABLED__
	if(!s_sign_timeout){
		htask = s_list_timeout;
		while(htask != OS_VOID){
			if(htask->status == OS_STATUS_TIMEOUT){
				htask->srt_counter = 0;
				htask->status = OS_STATUS_READY;
				sv_task_add_ready(htask);
			}
			else if(htask->status & OS_STATUS_SUSPENDED){
				htask->srt_counter = 0;
				htask->status = OS_STATUS_SUSPENDED;
			}
			else if(htask->status == OS_STATUS_DELETED){
				if(htask->create && htask->next_b == OS_NULL){
					sv_free_task(htask);
				}
			}
			s_list_timeout = htask->next_t;
			htask->next_t = OS_NULL;
			htask = s_list_timeout;
		}
	}
	if(s_task_current->pri && s_task_current->saferuntime){
		s_task_current->srt_counter++;
		if(s_task_current->srt_counter > 1UL * s_task_current->saferuntime * OS_TIMESHARING(s_task_current)){
			if(s_task_current->status == OS_STATUS_READY){
				s_task_current->next_t = s_list_timeout;
				s_list_timeout = s_task_current;
				sv_task_remove_ready(s_task_current);
				s_task_current->status = OS_STATUS_TIMEOUT;
				s_sign_timeout = true;
				#if SYSCFG_DEBUGGING == __ENABLED__
				s_alarm.timeout_saferuntime = true;
				#endif
			}
		}
	}
	#endif
	
	/* 任务管理器 */
	#if SYSCFG_DEBUGGING == __ENABLED__
	if(s_sign_taskmgr){
		usedtime[0]++; /*!< CPU使用时间计数 */
		#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__
		mSysTick_Counting; /*!< 系统滴答时间统计结束 */
		#endif
	}
	#endif
	
	/* 任务调度 */
	if(s_sign_schedule && !s_sign_schedule_forbid){
		mPendSV_Set;
	}
}

s_tasknode_tsp  _SYS_MEM_ s_task_news = OS_NULL;
#if SYSCFG_DEBUGGING == __ENABLED__
m_stacksize_t   _SYS_MEM_ s_taskstacklen;
#endif

#if SYSCFG_MCUCORE == 80251
#pragma functions(static)
#endif
s_u8_t sPendSV_Handler(void) MCUCFG_C51USING
{
	void pendsv_hook(void);
	void copy_hook(void);
	sCat2Str(SYSCFG_STARTERCREATE, ExternTask(Starter));
	
	/* 中断挂起服务_FIFO */
	#if MCUCFG_PENDSVFIFO_DEPTH > 0
	mPendSV_FIFOHandle;
	#endif
	
	/* 中断挂起服务_FLAG */
	#if SYSCFG_PENDSVHOOK == __ENABLED__
	pendsv_hook();
	#endif
	
	/* 更新全局变量副本 */
	#if SYSCFG_GETRTC_INT == __ENABLED__
	if(s_sign_rtc){
		s_sign_rtc = false;
		sv_update_rtccopy();
	}
	#endif
	#if SYSCFG_COPYHOOK == __ENABLED__
	sUpdateCopy(copy_hook());
	#endif
	
	/* 每PendSV监控（假定入栈）*/
	#if SYSCFG_DEBUGGING == __ENABLED__
	if(s_task_current != OS_NULL){
		if(s_task_current->stacklen_max < s_taskstacklen){
			s_task_current->stacklen_max = s_taskstacklen;
			if(s_task_current->stacksize < s_taskstacklen){
				s_alarm.overflow_taskstack = true;
			}
		}
	}
	#endif
	
	/* 任务调度 */
	if(s_sign_schedule_forbid) return 0;
	if(s_sign_schedule){
		s_tasknode_tsp _SYS_REG_ node_news;
		m_bit_t sign_push = false; /*!< 入栈信号 */
		#if SYSCFG_SAMEPRISCHEDULE
		s_u8_t _SYS_REG_ pri;
		#endif
		#if SYSCFG_DEBUGGING == __ENABLED__
		m_tick_t _SYS_REG_ tick_counter;
		#endif
		s_sign_schedule = false;
		
		/* 启动任务 */
		if(s_task_starter != OS_NULL){
			/* 静态创建 */
			if(*s_task_starter->dualhandle != OS_NULL){
				node_news = (s_tasknode_tsp)s_task_starter;
				if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){
					#if SYSCFG_DEBUGGING == __ENABLED__
					s_fault.failed_startuptask = true;
					s_fault.overflow_taskstack = true;
					#endif
					s_startup_code = OS_ECODE_OVERFLOW_TASKSTACK;
					goto __STARTUP_END;
				}
				else{
					mTaskStack_INIT;
				}
			}
			/* 动态创建 */
			else{
				node_news = OS_NULL;
				node_news = (s_tasknode_tsp)s_malloc(sizeof(s_tasknode_ts));
				if(node_news != OS_NULL){
					node_news->stacksize = s_task_starter->stacksize;
					if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){
						node_news->stacksize = MCUCFG_BASICSTACKSIZE;
						node_news->create = 2;
					}
					else{
						node_news->create = 1;
					}
					node_news->bsp = OS_NULL;
					node_news->bsp = (s_u8_t _MALLOC_MEM_ *)s_malloc(node_news->stacksize);
					if(node_news->bsp != OS_NULL){
						mTaskStack_INIT;
						node_news->opri = s_task_starter->opri;
						node_news->dualhandle = s_task_starter->dualhandle;
						*node_news->dualhandle = node_news;
						#if SYSCFG_DEBUGGING == __ENABLED__
						node_news->name = s_task_starter->name;
						#endif
						#if SYSCFG_SAFERUNTIME == __ENABLED__
						node_news->saferuntime = s_task_starter->saferuntime;
						#endif
					}
					else{
						s_free(node_news);
						#if SYSCFG_DEBUGGING == __ENABLED__
						s_fault.failed_startuptask = true;
						s_fault.mallocfailed_taskstack = true;
						#endif
						s_startup_code = OS_ECODE_MALLOCFAIL_TASKSTACK;
						goto __STARTUP_END;
					}
				}
				else{
					#if SYSCFG_DEBUGGING == __ENABLED__
					s_fault.failed_startuptask = true;
					s_fault.mallocfailed_tasknode = true;
					#endif
					s_startup_code = OS_ECODE_MALLOCFAIL_TASKNODE;
					goto __STARTUP_END;
				}
			}
			/* 公共部分 */
			if(node_news->opri <= (s_u8_t)(SYSCFG_TASKPRIORITY - 2)){
				node_news->pri = node_news->opri;
			}
			else{
				node_news->pri = SYSCFG_TASKPRIORITY - 2;
				#if SYSCFG_DEBUGGING == __ENABLED__
				s_alarm.outrange_taskpriority = true;
				#endif
			}
			node_news->status = s_task_status0;
			node_news->blocktype = 0;
			node_news->timer = 0;
			#if SYSCFG_MCUCORE == 8051
			node_news->handle = OS_NULL;
			#endif
			#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
			node_news->tc_counter = 0;
			#endif
			#if SYSCFG_DEBUGGING == __ENABLED__
			node_news->usedtime[0] = 0;
			node_news->usedtime[1] = 0;
			node_news->stacklen_max = MCUCFG_BASICSTACKSIZE;
			#endif
			#if SYSCFG_SAFERUNTIME == __ENABLED__
			node_news->srt_counter = 0;
			#endif
			node_news->next_b = OS_NULL;
			node_news->next_t = OS_NULL;
			sv_insert_task_queue(node_news);
			s_task_queue_count++;
			if(s_task_status0 == OS_STATUS_READY){
				sv_task_add_ready(node_news);
				s_sign_schedule = false;
			}
			s_startup_code = OS_ECODE_NOERROR;
			__STARTUP_END:
			s_task_starter = OS_NULL;
			if(node_news == u_taskhandle_Starter){
				goto __NEWTASK_PREPROCESS; /*!< 首次任务调度 -> 新任务预处理 */
			}
			else{
				return 0;
			}
		}
		
		/* 任务调度 */
		#if SYSCFG_SAMEPRISCHEDULE
		pri = sv_task_select_ready();
		node_news = s_task_queue[pri];
		while(true){
			#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
			s_tasknode_tsp _SYS_REG_ node_temp;
			#endif
			if(node_news->status == OS_STATUS_READY){
				#if SYSCFG_SAMEPRISCHEDULE == __COOPERATIVE__
				break;
				#elif SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
				if(node_news->tc_counter < OS_TIMESHARING(node_news)){ /* 时间片未到期 */
					break;
				}
				else{ /* 时间片已到期 */
					node_news->tc_counter = 0;
					node_temp = node_news;
				}
				#endif
			}
			#if SYSCFG_SAMEPRISCHEDULE == __COOPERATIVE__
			node_news = node_news->next;
			#elif SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
			if(node_news != s_task_queue[pri]->last){
				node_news = node_news->next;
			}
			else{
				node_news = node_temp;
				break; /* 在该优先级组中，未能找到时间片未到期的就绪任务，继续已到期的就绪任务 */
			}
			#endif
		}
		#else
		node_news = s_task_queue[sv_task_select_ready()];
		#endif
		
		if(node_news == s_task_current){ /* 新任务仍为当前任务 -> 返回 */
			goto __TASKING_RETURN;
		}
		#if SYSCFG_SAMEPRISCHEDULE
		else if(node_news != s_task_queue[pri]){ /* 新任务轮转至其优先级组首节点 */
			s_task_queue[pri] = node_news;
		}
		#endif
		
		/* 当前任务后处理 */
		if(s_task_current->status < OS_STATUS_STOPPED){
			#if SYSCFG_DEBUGGING == __ENABLED__ /* 入栈监控 */
			if(s_task_current->stacksize < s_taskstacklen){
				#if MCUCFG_TASKSTACK_REALLOC == __ENABLED__
				if(s_task_current->create){
					s_task_current->stacksize = s_taskstacklen + MCUCFG_TASKSTACKREALLOC_INC;
					s_free(s_task_current->bsp);
					s_task_current->bsp = OS_NULL;
					s_task_current->bsp = (s_u8_t _MALLOC_MEM_ *)s_malloc(s_task_current->stacksize);
					if(s_task_current->bsp != OS_NULL){
						sign_push = true;
						s_task_current->create = 2;
						s_alarm.realloc_taskstack = true;
					}
					else{
						s_task_current->status = OS_STATUS_STOPPED;
						s_fault.reallocfailed_taskstack = true;
					}
				}
				else{
					s_task_current->status = OS_STATUS_STOPPED;
					s_fault.overflow_taskstack = true;
				}
				#else
				s_task_current->status = OS_STATUS_STOPPED;
				s_fault.overflow_taskstack = true;
				#endif
			}
			else{
				sign_push = true;
			}
			#else
			sign_push = true;
			#endif
		}
		
		/* 新任务预处理 */
		__NEWTASK_PREPROCESS:{
			#if SYSCFG_DEBUGGING == __ENABLED__
			if(s_sign_taskmgr) tick_counter = mSysTick_Counter;
			#endif
		}
		
		/* 当前任务入栈 */
		if(sign_push){
			#if SYSCFG_SAFERUNTIME == __ENABLED__
			if(s_task_current->pri > node_news->pri){
				s_task_current->srt_counter = 0;
			}
			#endif
			#if SYSCFG_DEBUGGING == __ENABLED__
			if(s_sign_taskmgr) mUsedTime_END;
			#endif
			mUserReg_CSave;
		}
		
		/* 新任务出栈 */
		if(true){
			if(node_news->blocktype != OS_BLOCKED_DELAY){
				mSysIRQ_Disable;
			}
			#if SYSCFG_DEBUGGING == __ENABLED__
			if(s_sign_taskmgr) mUsedTime_INIT;
			#endif
			mUserReg_CRes;
			s_task_news = node_news;
		}
		
		if(sign_push) return 2;
		else return 1;
	}
	
	__TASKING_RETURN:{
		if(s_task_current->blocktype){
			s_task_current->blocktype &= 0x0F;
			mSysIRQ_Disable;
		}
		return 0;
	}
}
